package per.sunmes.cl.g.screen;

import per.sunmes.cl.g.actor.Card;
import per.sunmes.cl.g.actor.Player;
import per.sunmes.cl.g.actor.Zone;
import per.sunmes.cl.g.actor.ef.BlendPic;
import per.sunmes.cl.g.data.CardData;
import per.sunmes.cl.g.data.SimpleEnemyAI;
import per.sunmes.cl.g.data.type.RoundType;
import per.sunmes.cl.g.gsys.CardFactory;
import per.sunmes.cl.g.i.Ai;
import per.sunmes.cl.g.i.CallAction;
import per.sunmes.cl.g.sys.G;
import per.sunmes.cl.g.sys.LM;
import per.sunmes.cl.g.sys.RandU;
import per.sunmes.cl.g.sys.U;

import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.NinePatch;
import com.badlogic.gdx.math.Interpolation;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.Action;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.Group;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.InputListener;
import com.badlogic.gdx.scenes.scene2d.actions.Actions;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.Label.LabelStyle;
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
import com.badlogic.gdx.utils.Align;
import com.badlogic.gdx.utils.Array;

public class GameScreen extends Group {

	Group zoneGroup;
	Group zonePreviewGroup;
	Actor zoneGroupSizeActor;
	Group gameGroup;
	Group uiGroup;

	float zoneScale;
	float zoneWidth, zoneHeight;

	Zone[][] zoneMap;

	Player player;
	Player enemy;
	Ai enemyAi;
	Player firstPlayer, secondPlayer;
	Image playerLand, enemyLand;
	Image error;
	BlendPic landSelectSign;
	Image picArrow;
	Group arrow;
	Card playerCardArray, enemyCardArray;
	Label labelPlayerCardLeft, labelEnemyCardLeft;
	// Label labelPlayerPoint, labelEnemyPoint;
	Label msgLabel;
	Image msgBg;

	Label debugLabel;

	Actor updateActorSelecters = new Actor();
	Actor roundActor = new Actor();

	boolean isPlayerUsedCard;

	static final float HC_WIDTH = 270 * 0.63f, HC_HEIGHT = 380 * 0.63f,//
			HCO_WIDTH = 270, HCO_HEIGHT = 380//
			;

	RoundType currentRound;

	public GameScreen() {
		U.stageSize(this);
		setTransform(false);

		Image bg = U.image("dialog/bg.png");
		addActor(bg);

		zoneGroup = new Group();
		addActor(zoneGroup);
		zonePreviewGroup = new Group();
		U.disTouch(zonePreviewGroup);
		addActor(zonePreviewGroup);
		gameGroup = new Group();
		U.stageSize(gameGroup);
		gameGroup.setTransform(false);
		addActor(gameGroup);
		uiGroup = new Group();
		uiGroup.setTransform(false);
		U.stageSize(uiGroup);
		addActor(uiGroup);

		initZoneGroup();
		initPlayers();
		initPlayer1and2();

		initUpdataActors();

		initUI();
	}

	private void initUI() {
		msgBg = U.createMask();
		msgBg.setColor(Color.RED);
		msgBg.setSize(460, 50);
		uiGroup.addActor(msgBg);
		msgBg.setPosition(getWidth() / 2, 120, Align.bottom);

		msgLabel = new Label("MSG", new LabelStyle(U.getCardNameFont(),
				Color.WHITE));
		uiGroup.addActor(msgLabel);
		msgLabel.setAlignment(Align.center);
		U.center(msgLabel, msgBg);

		msgLabel.setVisible(false);
		msgBg.setVisible(false);
		// ////////////// Msg Labels.
		picArrow = new Image(new NinePatch(U.region("dialog/sign_arrow.png"),
				45, 15, 24, 24));
		arrow = new Group();
		arrow.addActor(picArrow);
		arrow.setSize(picArrow.getWidth(), picArrow.getHeight());
		uiGroup.addActor(arrow);

		error = U.image("dialog/sign_error.png");
		zoneGroup.addActor(error);
		error.setPosition(zoneGroup.getWidth() / 2, zoneGroup.getHeight() / 2,
				Align.center);
		error.setVisible(false);

		landSelectSign = new BlendPic(U.region("dialog/land_select.png"));
		zoneGroup.addActor(landSelectSign);
		landSelectSign.setVisible(false);
		landSelectSign.setOrigin(Align.center);
		landSelectSign.addAction(Actions.repeat(
				-1,
				Actions.sequence(Actions.alpha(0.5f, 0.5f),
						Actions.alpha(1, 0.5f))));
		// /////////
		debugLabel = new Label("DEBUG..", new LabelStyle(U.getCardTxtFont(),
				Color.RED));
		uiGroup.addActor(debugLabel);
		debugLabel.setAlignment(Align.topLeft);
		debugLabel.setPosition(10, getHeight() - 10, Align.topLeft);
	}

	private void initUpdataActors() {
		addInputListeners();
		//
		selectPosX = getWidth() - HC_WIDTH - 20;
		selectPosY = getHeight() / 2 - HC_HEIGHT / 2 + 60;

		addActor(updateActorSelecters);
		updateActorSelecters.addAction(new Action() {
			@Override
			public boolean act(float delta) {
				updatePointCardShow(delta);
				updateZoneShow(delta);
				return false;
			}
		});

		addActor(roundActor);
	}

	public void currentPlayerUsedCard() {
		isPlayerUsedCard = true;
	}

	final float POINTCARD_DELAY = 0.1f;
	Card currentSelectedCard;
	Zone currentSelectedZone, lastSelectedZone;

	protected void updateZoneShow(float delta) {
		currentSelectedZone = mousePointSelectedZone();
		// debugLabel.setText(String.format("cZone:%s", currentSelectedZone));
		if (currentSelectedZone != null) {
			if (lastSelectedZone != currentSelectedZone) {
				lastSelectedZone = currentSelectedZone;
				zonePreviewGroup.clear();

				landSelectSign.setVisible(true);
				landSelectSign.setZIndex(zoneGroup.getChildren().size + 1);
				landSelectSign.getColor().a = 0;
				U.center(landSelectSign, currentSelectedZone);

				if (isCouldPlayerUseCard() && currentSelectedCard != null) {
					presetZone(currentSelectedZone, currentSelectedCard);
				}
			}
		} else {
			if (error.isVisible()) {
				error.setVisible(false);
			}
			if (landSelectSign.isVisible()) {
				landSelectSign.setVisible(false);
			}
			if (lastSelectedZone != null) {
				lastSelectedZone = null;
				zonePreviewGroup.clear();
			}
		}
	}

	private void presetZone(Zone zone, Card card) {
		if (!isZoneCouldPutCard(zone, card)) {
			error.setVisible(true);
			error.setZIndex(zoneGroup.getChildren().size + 1);
			U.center(error, zone);
		} else {
			card.getCardData().getEffect()
					.preEffect(this, zone, card, zonePreviewGroup);

			if (error.isVisible()) {
				error.setVisible(false);
			}
		}
	}

	private boolean isZoneCouldPutCard(Zone zone, Card card) {
		return card.isCouldPutToZone(zone);
	}

	private void updatePointCard() {
		// debugLabel.setText(String.format("MOUSE:%.2f-%.2f", mousePoint.x,
		// mousePoint.y));

		boolean isHasOneHited = currentSelectedCard != null;

		for (int i = player.getHandCards().size - 1; i >= 0; i--) {
			Card card = player.getHandCards().get(i);
			if (!isHasOneHited
					&& U.rectHit(mousePoint.x, mousePoint.y,
							card.getOrderPos().x, 0, HC_WIDTH,
							PLAYER_HAND_CARD_BASEY)) {
				card.setZIndex(gameGroup.getChildren().size);
				card.addAction(Actions.parallel(Actions.scaleTo(1.2f, 1.2f,
						POINTCARD_DELAY), Actions.moveTo(card.getOrderPos().x,
						card.getHeight() * 0.2f, POINTCARD_DELAY)));
				isHasOneHited = true;
			} else if (currentSelectedCard != card) {
				if ((card.getX() != card.getOrderPos().x
						|| card.getY() != card.getOrderPos().y || card
						.getScaleX() != 1) && !card.hasActions()) {
					card.addAction(Actions.parallel(
							Actions.scaleTo(1, 1, POINTCARD_DELAY),
							Actions.moveTo(card.getOrderPos().x,
									card.getOrderPos().y, POINTCARD_DELAY)));
				}
				if (card.getZIndex() != i) {
					card.setZIndex(i);
				}
			}
		}
		if (!isHasOneHited) {
			currentSelectedCard = null;
		}
	}

	static float selectPosX, selectPosY;

	private void updateSelectedCard() {
		if (!isTouched) {
			currentSelectedCard = null;
			return;
		}

		if (currentSelectedCard == null) { // select one
			for (int i = player.getHandCards().size - 1; i >= 0; i--) {
				Card card = player.getHandCards().get(i);
				if (U.rectHit(touchDownPos.x, touchDownPos.y,
						card.getOrderPos().x, 0, HC_WIDTH,
						PLAYER_HAND_CARD_BASEY)) {
					currentSelectedCard = card;
					break;
				}
			}
		}
		if (!isCouldPlayerUseCard() && currentSelectedCard != null) {
			if (!msgLabel.isVisible() && !msgLabel.hasActions()) {
				gameMsg("现在不是你的出牌回合!");
			}
			return;
		}

		if (currentSelectedCard != null) {
			if (!currentSelectedCard.hasActions()
					&& (currentSelectedCard.getY() != selectPosY || currentSelectedCard
							.getX() != selectPosX)) {
				currentSelectedCard.addAction(Actions.moveTo(selectPosX,
						selectPosY, POINTCARD_DELAY));
			}
			if (!arrow.isVisible()) {
				arrow.setVisible(true);
			}
			float x = currentSelectedCard.getX();
			float y = currentSelectedCard.getY()
					+ currentSelectedCard.getHeight() / 2;
			float r = MathUtils.atan2(y - mousePoint.y, x - mousePoint.x)
					* MathUtils.radiansToDegrees;
			arrow.setWidth(Vector2.len(mousePoint.x - x, mousePoint.y - y));
			picArrow.setSize(arrow.getWidth(), arrow.getHeight());
			arrow.setOrigin(Align.right);
			arrow.setPosition(x, y, Align.right);
			arrow.setRotation(r);

			if (!U.actorHit(zoneGroupSizeActor, mousePoint.x, mousePoint.y)) {
				picArrow.setColor(Color.RED);
				picArrow.getColor().a = 0.3f;
			} else {
				picArrow.setColor(Color.WHITE);
				picArrow.getColor().a = 1f;
			}
		}
	}

	private Zone mousePointSelectedZone() {
		float vx = mousePoint.x - zoneGroupSizeActor.getX();
		float vy = mousePoint.y - zoneGroupSizeActor.getY();
		int px = (int) (vx / zoneWidth);
		int py = (int) (vy / zoneHeight);

		if (vx < 0 || vy < 0) {
			return null;
		}
		// debugLabel.setText(String.format("vxy[%.2f,%.2f] p[%d,%d]", vx, vy,
		// px,
		// py));

		if (px < 0 || px >= LM.mapXCount || py < 0 || py >= LM.mapYCount) {
			return null;
		}
		return zoneMap[px][py];
	}

	public void gameMsg(String string) {
		gameMsg(string, 0.5f);
	}

	public void gameMsg(String string, float delay) {
		msgLabel.setText(string);
		if (msgLabel.isVisible() || msgLabel.hasActions()) {
			msgLabel.clearActions();
			msgBg.clearActions();
		}
		msgLabel.addAction(Actions.sequence(Actions.sequence(
				Actions.visible(true), Actions.fadeIn(0), Actions.delay(delay),
				Actions.fadeOut(0.2f), Actions.visible(false))));
		msgBg.addAction(Actions.sequence(Actions.sequence(
				Actions.visible(true), Actions.fadeIn(0), Actions.delay(delay),
				Actions.fadeOut(0.2f), Actions.visible(false))));
	}

	public boolean isCouldPlayerUseCard() {
		if (isPlayerUsedCard || roundActor.hasActions()) {
			return false;
		}
		if (isPlayerFirstPlayer()) {
			return currentRound == RoundType.Player1UseCardRound;
		} else {
			return currentRound == RoundType.Player2UseCardRound;
		}
	}

	protected void updatePointCardShow(float delta) {
		updatePointCard();
		updateSelectedCard();
		if (currentSelectedCard == null) {
			if (arrow.isVisible()) {
				arrow.setVisible(false);
			}
		}
	}

	private void initPlayer1and2() {
		// 随机
		int p1 = RandU.rand(1, 3);
		String msg;
		if (p1 == 1) {
			firstPlayer = player;
			secondPlayer = enemy;
			msg = "先手";
		} else {
			firstPlayer = enemy;
			secondPlayer = player;
			msg = "后手";
		}
		// //
		U.msg(msg);
		addAction(Actions.sequence(Actions.delay(1.5f), new CallAction() {
			public void call() {
				startGame();
			}
		}));
	}

	private void startGame() {
		// //////
		currentRound = RoundType.FirstDrawRound;
		debugLabel.setText("ROUND:" + currentRound);
		animationExecuteRound();
	}

	private Action actionExecuteNextRound() {
		return new CallAction() {
			public void call() {
				int i = currentRound.ordinal() + 1;
				if (i >= RoundType.values().length) {
					i = 1;
				}
				currentRound = RoundType.values()[i];
				debugLabel.setText("ROUND:" + currentRound);
				animationExecuteRound();
			}
		};
	}

	private void animationExecuteRound() {
		String info = null;
		switch (currentRound) {
		case FirstDrawRound:
			info = "初始抽牌阶段";
			break;
		case Player1DrawCardRound:
			break;
		case Player1RoundEnd:
			break;
		case Player1UseCardRound:
			info = isPlayerFirstPlayer() ? "你的回合" : "对方回合";
			break;
		case Player2DrawCardRound:
			break;
		case Player2RoundEnd:
			break;
		case Player2UseCardRound:
			info = isPlayerFirstPlayer() ? "对方回合" : "你的回合";
			break;
		default:
			break;
		}

		if (info != null) {
			U.msg(info, 0.5f);
			roundActor.clearActions();
			roundActor.addAction(Actions.sequence(Actions.delay(0.3f),
					new CallAction() {
						public void call() {
							executeRound();
						}
					}));
		} else {
			executeRound();
		}
	}

	private boolean isPlayerFirstPlayer() {
		return firstPlayer == player;
	}

	private void executeRound() {
		switch (currentRound) {
		case FirstDrawRound:
			roundFirstDraw();
			break;
		case Player1DrawCardRound:
			roundPlayer1DrawCard();
			break;
		case Player1RoundEnd:
			roundPlayer1RoundEnd();
			break;
		case Player1UseCardRound:
			roundPlayer1UseCard();
			break;
		case Player2DrawCardRound:
			roundPlayer2DrawCard();
			break;
		case Player2RoundEnd:
			roundPlayer2RoundEnd();
			break;
		case Player2UseCardRound:
			roundPlayer2UseCard();
			break;
		default:
			break;
		}
	}

	private void roundPlayer2UseCard() {
		isPlayerUsedCard = false;
		if (isPlayerFirstPlayer()) {
			enemyAi.useCard();
		} else {
			if (player.getHandCards().size < 1) {
				delayActionExecuteNextRound(0f);
			}
		}
	}

	private void roundPlayer2RoundEnd() {
		if (checkWinEnd()) {
			return;
		}
		if (isPlayerFirstPlayer()) {
			enemyAi.roundEnd();
		}
		delayActionExecuteNextRound(0.2f);
	}

	private void roundPlayer2DrawCard() {
		if (!isPlayerFirstPlayer()) {
			if (player.getCardArrays().size < 1) {
				delayActionExecuteNextRound(0);
				return;
			}
			playerDrawCard(0);
		} else {
			if (enemy.getCardArrays().size < 1) {
				delayActionExecuteNextRound(0);
				return;
			}
			enemyDrawCard(0);
		}
		delayActionExecuteNextRound(1.5f);
	}

	private void roundPlayer1UseCard() {
		isPlayerUsedCard = false;
		if (!isPlayerFirstPlayer()) {
			enemyAi.useCard();
		} else if (player.getHandCards().size < 1) {
			delayActionExecuteNextRound(0);
		}
	}

	private void roundPlayer1RoundEnd() {
		if (checkWinEnd()) {
			return;
		}
		if (!isPlayerFirstPlayer()) {
			enemyAi.roundEnd();
		}
		delayActionExecuteNextRound(0.2f);
	}

	private void roundPlayer1DrawCard() {
		if (isPlayerFirstPlayer()) {
			if (player.getCardArrays().size < 1) {
				delayActionExecuteNextRound(0);
				return;
			}
			playerDrawCard(0);
		} else {
			if (enemy.getCardArrays().size < 1) {
				delayActionExecuteNextRound(0);
				return;
			}
			enemyDrawCard(0);
		}
		delayActionExecuteNextRound(1.5f);
	}

	private void roundFirstDraw() {
		for (int i = 0; i < 5; i++) {
			playerDrawCard(i * 0.4f);
			enemyDrawCard(i * 0.4f);
		}
		delayActionExecuteNextRound(0.4f * 5 + 1.5f);
	}

	public void delayActionExecuteNextRound(float delay) {
		roundActor.clearActions();
		roundActor.addAction(Actions.sequence(Actions.delay(delay),
				actionExecuteNextRound()));
	}

	public static float PLAYER_HAND_CARD_BASEY = 100, ENEMY_HAND_CARD_BASEY;

	public void enemyDrawCard(float delay) {
		if (enemy.getCardArrays().size < 1) {
			return;
		}
		CardData cd = enemy.getCardArrays().removeIndex(0);
		Card card = new Card();
		card.setSize(HC_WIDTH, HC_HEIGHT);
		card.updateSize();

		card.changeBackBg(enemyCardArray.getBbg().getDrawable());
		card.setPlayer(enemy);
		card.setCardData(cd);
		card.updateCardData();
		card.updateToPlayerCard();
		card.showBackPage();

		gameGroup.addActor(card);
		card.setZIndex(enemyCardArray.getZIndex() + 1);
		card.setOrigin(Align.center);
		U.center(card, enemyCardArray);
		card.setScale(enemyCardArray.getHeight() * enemyCardArray.getScaleX()
				/ card.getHeight());
		card.addAction(Actions.sequence(//
				Actions.delay(delay)//
				, Actions.parallel(//
						Actions.moveBy(130, -60, 0.2f, Interpolation.sineIn)//
						, Actions.scaleTo(1 / card.getWidth(), 0.5f, 0.2f,
								Interpolation.sineIn)//
						)//
							// , new CallAction(card) {
				// public void call() {
				// Card card = (Card) obj;
				// card.showFrontPage();
				// }
				// }//
				, Actions.parallel(//
						Actions.moveToAligned(840, getHeight() - 100,
								Align.center, 0.3f, Interpolation.sineOut)//
						, Actions.scaleTo(1, 1, 0.3f, Interpolation.sineOut)//
						)//
				, Actions.moveTo(840 - card.getWidth() / 2, getHeight() - 130,
						0.5f)//
				, new CallAction(card) {
					public void call() {
						Card card = (Card) obj;
						enemy.getHandCards().add(card);
						resetPlayerHandCard(enemy);
					}
				}));

	}

	public void playerDrawCard(float delay) {
		if (player.getCardArrays().size < 1) {
			return;
		}
		CardData cd = player.getCardArrays().removeIndex(0);
		Card card = new Card();
		card.setSize(HC_WIDTH, HC_HEIGHT);
		card.updateSize();

		card.setOrigin(Align.center);

		card.changeBackBg(playerCardArray.getBbg().getDrawable());
		card.setPlayer(player);
		card.setCardData(cd);
		card.updateCardData();
		card.updateToPlayerCard();
		card.showBackPage();

		gameGroup.addActor(card);
		card.setZIndex(playerCardArray.getZIndex() + 1);
		card.setOrigin(Align.center);
		U.center(card, playerCardArray);
		card.setScale(playerCardArray.getHeight() * playerCardArray.getScaleX()
				/ card.getHeight());
		card.addAction(Actions.sequence(//
				Actions.delay(delay)//
				, Actions.parallel(//
						Actions.moveBy(130, 60, 0.2f, Interpolation.sineIn)//
						, Actions.scaleTo(1 / card.getWidth(), 0.5f, 0.2f,
								Interpolation.sineIn)//
						)//
				, new CallAction(card) {
					public void call() {
						Card card = (Card) obj;
						card.showFrontPage();
					}
				}//
				, Actions.parallel(//
						Actions.moveToAligned(840, 300, Align.center, 0.3f,
								Interpolation.sineOut)//
						, Actions.scaleTo(1, 1, 0.3f, Interpolation.sineOut)//
						)//
				, Actions.moveTo(840 - card.getWidth() / 2,
						130 - card.getHeight(), 0.5f)//
				, new CallAction(card) {
					public void call() {
						Card card = (Card) obj;
						player.getHandCards().add(card);
						resetPlayerHandCard(player);
					}
				}));
	}

	Vector2 touchDownPos = new Vector2(), touchUpPos = new Vector2(),
			mousePoint = new Vector2();
	boolean isTouched;

	private void addInputListeners() {
		G.gameActor.addListener(new InputListener() {
			@Override
			public boolean mouseMoved(InputEvent event, float x, float y) {
				mousePoint.set(x, y);
				return false;
			}

			@Override
			public boolean touchDown(InputEvent event, float x, float y,
					int pointer, int button) {
				isTouched = true;
				touchDownPos.set(x, y);
				return true;
			}

			@Override
			public void touchDragged(InputEvent event, float x, float y,
					int pointer) {
				mousePoint.set(x, y);
			}

			@Override
			public void touchUp(InputEvent event, float x, float y,
					int pointer, int button) {
				isTouched = false;
				touchUpPos.set(x, y);
				putCardCheck();
			}
		});
	}

	protected void putCardCheck() {
		if (!isCouldPlayerUseCard()) {
			return;
		}
		if (currentSelectedZone != null && currentSelectedCard != null
				&& isZoneCouldPutCard(currentSelectedZone, currentSelectedCard)) {
			currentSelectedCard.getCardData().getEffect()
					.effect(this, currentSelectedZone, currentSelectedCard);
			currentSelectedZone = null;
			currentSelectedCard = null;

			isPlayerUsedCard = true;

			resetPlayerHandCard(player);
			// used card nextRound.由卡牌自己触发.
		}
	}

	float handZoneMoveOff = 70, handZoneSize = 900;

	public void resetPlayerHandCard(Player p) {
		float baseY = (p == player ? PLAYER_HAND_CARD_BASEY
				: ENEMY_HAND_CARD_BASEY);
		int size = p.getHandCards().size;
		float offX = handZoneSize / size;
		float rx = (size % 2 == 0 ? 0.5f : 0);
		float wid = Math.min(HC_WIDTH, offX);
		for (int i = 0; i < size; i++) {
			Card card = p.getHandCards().get(i);
			card.clearActions();
			card.getOrderPos().set(
					handZoneMoveOff + handZoneSize / 2 + (i - size / 2 + rx)
							* wid - card.getWidth() / 2,
					baseY - card.getHeight());

			if (p != player || currentSelectedCard != card) {
				card.addAction(Actions.moveTo(card.getOrderPos().x,
						card.getOrderPos().y, 0.2f));
			}
		}
	}

	private void initPlayers() {
		player = new Player();
		player.setLandPicPath("dialog/land_1.png");
		player.setPlayerColor(new Color(147 / 255f, 247 / 255f, 66 / 255f, 1));
		// /////
		playerLand = U.image(player.getLandPicPath());
		zoneGroup.addActor(playerLand);
		playerLand.setVisible(false);
		playerLand.getColor().a = 0.5f;
		// ////
		initDemoPlayerCard(player);
		playerCardArray = new Card();
		playerCardArray.changeBackBg(new TextureRegionDrawable(U
				.region("dialog/card_back_1.png")));
		gameGroup.addActor(playerCardArray);
		playerCardArray.showBackPage();
		playerCardArray.setOrigin(Align.center);
		playerCardArray.setScale(0.4f);
		playerCardArray.setPosition(1130, 10, Align.bottom);
		labelPlayerCardLeft = new Label("剩余:36张", new LabelStyle(
				U.getCardNameFont(), Color.WHITE));
		uiGroup.addActor(labelPlayerCardLeft);
		labelPlayerCardLeft.setAlignment(Align.center);
		U.center(labelPlayerCardLeft, playerCardArray);
		labelPlayerCardLeft.addAction(new Action() {
			int count = 0;

			@Override
			public boolean act(float delta) {
				if (count != player.getCardArrays().size) {
					count = player.getCardArrays().size;
					labelPlayerCardLeft.setText(String.format("剩余:%d张", count));
				}
				return false;
			}
		});

		enemy = new Player();
		enemy.setLandPicPath("dialog/land_2.png");
		enemy.setPlayerColor(new Color(66 / 255f, 147 / 255f, 247 / 255f, 1));
		// /////
		enemyLand = U.image(enemy.getLandPicPath());
		zoneGroup.addActor(enemyLand);
		enemyLand.setVisible(false);
		enemyLand.getColor().a = 0.5f;
		// ////
		initDemoPlayerCard(enemy);
		enemyCardArray = new Card();
		enemyCardArray.changeBackBg(new TextureRegionDrawable(U
				.region("dialog/card_back_2.png")));
		gameGroup.addActor(enemyCardArray);
		enemyCardArray.showBackPage();
		enemyCardArray.setOrigin(Align.center);
		enemyCardArray.setScale(0.4f);
		enemyCardArray.setPosition(1130, 640, Align.center);
		labelEnemyCardLeft = new Label("剩余:36张", new LabelStyle(
				U.getCardNameFont(), Color.WHITE));
		uiGroup.addActor(labelEnemyCardLeft);
		labelEnemyCardLeft.setAlignment(Align.center);
		U.center(labelEnemyCardLeft, enemyCardArray);
		labelEnemyCardLeft.addAction(new Action() {
			int count = 0;

			@Override
			public boolean act(float delta) {
				if (count != enemy.getCardArrays().size) {
					count = enemy.getCardArrays().size;
					labelEnemyCardLeft.setText(String.format("剩余:%d张", count));
				}
				return false;
			}
		});

		enemyAi = new SimpleEnemyAI(enemy, zoneMap, this);
		// /////////////
		PLAYER_HAND_CARD_BASEY = 100;
		ENEMY_HAND_CARD_BASEY = getHeight() - 30 + HC_HEIGHT;
	}

	private void initDemoPlayerCard(Player player) {
		// total 36;
		int[] counts = new int[] { 12, 2, 2, 4, 4, 4, 4, 4 };
		Array<CardData> cards = player.getCardArrays();
		for (int i = 0; i < counts.length; i++) {
			for (int c = 0; c < counts[i]; c++) {
				cards.insert(RandU.rand(0, cards.size),
						CardFactory.getCardCopy(i + 1));
			}
		}
	}

	final static float BASE_WIDTH = 900;
	final static float BASE_HEIGHT = 580;
	final static float ZONE_NW = 134;

	private void initZoneGroup() {
		float zoneTW = ZONE_NW * LM.mapXCount;
		float zoneTH = ZONE_NW * LM.mapYCount;
		zoneGroup.setSize(zoneTW, zoneTH);
		zoneGroup.setOrigin(Align.center);

		zoneGroup.setPosition(70 + 450, 100 + 580 / 2, Align.center);
		float wp = zoneGroup.getWidth() / BASE_WIDTH;
		float hp = zoneGroup.getHeight() / BASE_HEIGHT;
		if (wp > hp) {
			zoneScale = BASE_WIDTH / zoneGroup.getWidth();
		} else {
			zoneScale = BASE_HEIGHT / zoneGroup.getHeight();
		}
		zoneGroup.setScale(zoneScale);
		zoneWidth = ZONE_NW * zoneScale;
		zoneHeight = ZONE_NW * zoneScale;

		zonePreviewGroup.setSize(zoneGroup.getWidth(), zoneGroup.getHeight());
		zonePreviewGroup.setPosition(zoneGroup.getX(), zoneGroup.getY());
		zonePreviewGroup.setOrigin(Align.center);
		zonePreviewGroup.setScale(zoneGroup.getScaleX(), zoneGroup.getScaleY());

		zoneGroupSizeActor = new Actor();
		Vector2 p = new Vector2();
		zoneGroup.localToStageCoordinates(p);
		zoneGroupSizeActor.setPosition(p.x, p.y);
		zoneGroupSizeActor.setSize(
				zoneGroup.getWidth() * zoneGroup.getScaleX(),
				zoneGroup.getHeight() * zoneGroup.getScaleY());

		zoneMap = new Zone[LM.mapXCount][LM.mapYCount];
		for (int y = 0; y < LM.mapYCount; y++) {
			for (int x = 0; x < LM.mapXCount; x++) {
				Zone zone = new Zone();
				zone.setZoneMap(zoneMap);
				zone.setZoneX(x);
				zone.setZoneY(y);
				zoneMap[x][y] = zone;
				zoneGroup.addActor(zone);
				zone.setPosition(x * zone.getWidth(), y * zone.getHeight());
			}
		}

		// ///////
	}

	public boolean checkWinEnd() {
		boolean isCouldContinue = true;
		if (player.getHandCards().size < 1 && enemy.getHandCards().size < 1
				&& player.getCardArrays().size < 1
				&& enemy.getCardArrays().size < 1) {
			isCouldContinue = false;
		}
		// ///////////////////
		int pzc = 0;
		int ezc = 0;
		for (int y = 0; y < LM.mapYCount; y++) {
			for (int x = 0; x < LM.mapXCount; x++) {
				Zone zone = zoneMap[x][y];
				if (zone != null) {
					if (zone.getCard() == null) {
						if (isCouldContinue) {
							return false;
						}
					} else {
						if (zone.getPlayer() == player) {
							pzc++;
						} else if (zone.getPlayer() == enemy) {
							ezc++;
						}
					}
				}
			}
		}
		if (pzc == ezc) {
			U.msg("游戏结束.   平局 !", 99);
		} else {
			if (pzc > ezc) {
				U.msg(String.format("游戏结束.   胜利！  比分:%d:%d", pzc, ezc), 99);
			} else {
				U.msg(String.format("游戏结束.   失败！  比分:%d:%d", pzc, ezc), 99);
			}
		}
		gameMsg("按Esc键重新开始游戏", 99);
		return true;
	}

	public Action actionCardMoveToShowArea() {
		return Actions.moveTo(selectPosX, selectPosY, POINTCARD_DELAY);
	}

	public Player getOtherPlayer(Player p) {
		return p == player ? enemy : player;
	}

	public Player getPlayer() {
		return player;
	}

	public Player getEnemy() {
		return enemy;
	}

	public Group getGameGroup() {
		return gameGroup;
	}

	public Group getZoneGroup() {
		return zoneGroup;
	}

	public Actor getZoneGroupSizeActor() {
		return zoneGroupSizeActor;
	}

	public static float getSelectPosX() {
		return selectPosX;
	}

	public static float getSelectPosY() {
		return selectPosY;
	}

	public Player getFirstPlayer() {
		return firstPlayer;
	}

	public Player getSecondPlayer() {
		return secondPlayer;
	}

	public RoundType getCurrentRound() {
		return currentRound;
	}

	public Card getCurrentSelectedCard() {
		return currentSelectedCard;
	}

	public Zone getCurrentSelectedZone() {
		return currentSelectedZone;
	}

	public static float getHcHeight() {
		return HC_HEIGHT;
	}

	public static float getHcoHeight() {
		return HCO_HEIGHT;
	}

	public static float getHcoWidth() {
		return HCO_WIDTH;
	}

	public static float getHcWidth() {
		return HC_WIDTH;
	}

	public float getHandZoneMoveOff() {
		return handZoneMoveOff;
	}

	public void targetPlayerDrawCard(float delay, Player p) {
		if (p == player) {
			playerDrawCard(delay);
		} else {
			enemyDrawCard(delay);
		}
	}

}
